home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 293_01 / ang2.c < prev    next >
C/C++ Source or Header  |  1989-08-23  |  7KB  |  214 lines

  1. /*********************** ang2.c **************************************
  2.  
  3.       3-D Reconstruction of Medical Images
  4.  
  5.     Three Dimensional Reconstruction Of Medical
  6.     Images from Serial Slices - CT, MRI, Ultrasound
  7.  
  8.  
  9.    These programs process a set of slices images (scans) for one
  10.    patient. It outputs two sets of files containing nine predefined
  11.    views of bony surfaces. One set contains distance values and
  12.    the other gradient values.
  13.  
  14.    The distance values are used as 3-D spatial topographic surface
  15.    coordinate maps for geometrical analysis of the scanned object.
  16.  
  17.    The gradient values are used for rendering the surface maps on
  18.    CRT displays for subjective viewing where perception of small
  19.    surface details is important.
  20.  
  21.     Daniel Geist, B.S.
  22.     Michael W. Vannier, M.D.
  23.  
  24.     Mallinckrodt Institute of Radiology
  25.     Washington University School of Medicine
  26.     510 S. Kingshighway Blvd.
  27.     St. Louis, Mo. 63110
  28.  
  29.     These programs may be copied and used freely for non-commercial
  30.     purposes by developers with inclusion of this notice.
  31.  
  32.  
  33. ********************************************************************/
  34. #include <stdio.h>
  35. #include <math.h>
  36. #define FLOAT_LINE 1024
  37. #define PI 3.141592653
  38. /* the structure below is the data for a point on the surface projected
  39.    on the view plane                        */
  40. typedef struct DIS_REC {
  41.       float dist;            /*distance from view plane */
  42.       int indXY;             /* index of data on main axis view */
  43.       char XY;               /* Which main axis view obtained from (X or Y)*/
  44. };
  45. struct DIS_REC distances[256]; /* one projected line */ 
  46. int NLINES,IXmax,IYmax;
  47. float THETA,cosTheta,sinTheta,tgnTheta;
  48. float fxbuf[3][256],fybuf[3][256];/* input buffers */
  49. /*  output files  */
  50. char *fng="gang.out",*fnd="dang.out";
  51. succ(i)
  52. int i;
  53. {return(i==2?0:i+1);}
  54. prev(i)
  55. int i;
  56. {return(i==0?2:i-1);}
  57. /* PUTD - fill a DIS_REC with values */
  58. putd(pdis,D,i,xy_sym)
  59. struct DIS_REC *pdis;
  60. float D;
  61. int i,xy_sym;
  62. { pdis->dist=D;
  63.   pdis->indXY=i;
  64.   pdis->XY=xy_sym;
  65. }
  66. /* take one line from X and Y views and create a projrcted line */
  67. getdistances(linex,liney)
  68. float linex[],liney[];
  69. { int i,IND;
  70.   float D;
  71.   for(i=0;i<256;i++) distances[i].XY=0;
  72.   /* project Y-data onto image line */
  73.   for(i=0;i<256;i++){
  74.        IND=(255-i)*cosTheta-liney[i]*sinTheta;
  75.        D=liney[i]/cosTheta-(255-i-liney[i]*tgnTheta)*sinTheta;
  76.        IND=IXmax-IND;
  77.        if((IND>=0) && (IND<256)){
  78.            if(distances[IND].XY==0)putd(&distances[IND],D,i,1);
  79.            else if(distances[IND].dist>D)putd(&distances[IND],D,i,1);
  80.        }
  81.   }
  82.   /*project X-data onto image plane */
  83.   for(i=0;i<256;i++){
  84.        IND=(255-i)*sinTheta-linex[i]*cosTheta;
  85.        D=linex[i]/sinTheta-(255-i-linex[i]/tgnTheta)*cosTheta;
  86.        IND+=IXmax;
  87.        if((IND>=0) && (IND<256)){
  88.            if(distances[IND].XY==0)putd(&distances[IND],D,i,2);
  89.            else if(distances[IND].dist>D)putd(&distances[IND],D,i,2);
  90.        }
  91.   }
  92.   /* fill holes due to low resolution */
  93.   for(i=1;i<255;i++)if( (distances[i].XY==0) && (distances[i+1].XY!=0) &&
  94.             (distances[i-1].XY!=0))
  95.              putd(&distances[i],distances[i-1].dist,
  96.                    distances[i-1].indXY,(int)distances[i-1].XY);
  97. }
  98. /* returns gradient shade in point given the variations of the surface */
  99. unsigned char grad(x1,x2,y1,y2,z1,z2,x_fac,y_fac,z_fac)
  100. float x1,x2,y1,y2,z1,z2;
  101. int x_fac,y_fac,z_fac;
  102. {float gx,gy,gz,G,nx,ny;
  103.  unsigned char gxint;
  104.      /* components of gradient */
  105.   gx=(x2-x1)/x_fac;
  106.   gy=(y2-y1)/y_fac;
  107.   gz=(z1-z2)/z_fac;
  108.   G=sqrt(gx*gx+gy*gy+gz*gz);
  109.      /*compute nx,ny normalized x,y component of gradient */
  110.   nx=gx/G;
  111.   ny=gy/G;
  112.   gxint=255*(nx*sinTheta+ny*cosTheta)+0.5; /*scale gradient shade by 256 */
  113.   return(gxint);
  114. }
  115. doline(linex,linex1,liney,linex2,liney1,liney2,z_fac,fg,fd)
  116. float linex[],linex1[],linex2[],liney[],liney1[],liney2[];
  117. int z_fac;
  118. FILE *fg,*fd;
  119. { int i;
  120.   unsigned char lined[256],lineg[256];
  121.       /* empty bit on image line */
  122.   for(i=0;i<256;i++)if(distances[i].XY==0)lineg[i]=lined[i]=0;
  123.   else{
  124.       lined[i]=(distances[i].dist<256)?255-distances[i].dist:0;
  125.       /* bit on image line projected from Y view */
  126.       if(distances[i].XY==1) switch(distances[i].indXY){
  127.            case 0:lineg[i]=
  128.                    grad(liney[0],liney[1],(float)0,(float)2,
  129.                         liney1[0],liney2[0],1,2,z_fac);
  130.                   break;
  131.            case 255:lineg[i]=
  132.                     grad(liney[254],liney[255],(float)0,(float)2,
  133.                          liney1[255],liney2[255],1,2,z_fac);
  134.                   break;
  135.            default:lineg[i]=
  136.                    grad(liney[distances[i].indXY-1],
  137.                         liney[distances[i].indXY+1],(float)0,(float)2,
  138.                           liney1[distances[i].indXY],
  139.                           liney2[distances[i].indXY],2,2,z_fac); 
  140.                   break;
  141.       }
  142.       /* bit on image line projected from X view */
  143.       else switch(distances[i].indXY){
  144.            case 0:lineg[i]=
  145.                    grad((float)0,(float)2,linex[0],linex[1],
  146.                         linex1[0],linex2[0],2,1,z_fac);
  147.                   break;
  148.            case 255:lineg[i]=
  149.                     grad((float)0,(float)2,linex[254],linex[255],
  150.                          linex1[255],linex2[255],2,1,z_fac);
  151.                   break;
  152.            default:lineg[i]=
  153.                    grad((float)0,(float)2,linex[distances[i].indXY-1],
  154.                         linex[distances[i].indXY+1],
  155.                           linex1[distances[i].indXY],
  156.                           linex2[distances[i].indXY],2,1,z_fac);
  157.                   break;
  158.       }
  159.   }
  160.   fwrite(lineg,1,256,fg);
  161.   fwrite(lined,1,256,fd);
  162. }
  163. doviews()
  164. {FILE *fg,*fd,*fx,*fy;
  165.  int z,i,j,k,mid;
  166.  mid=1;
  167.  fd=fopen(fnd,"wb");
  168.  fg=fopen(fng,"wb");
  169.  fx=fopen("xdis.dat","rb");
  170.  fy=fopen("ydis.dat","rb");
  171.  fread(fxbuf,1,3*FLOAT_LINE,fx);
  172.  fread(fybuf,1,3*FLOAT_LINE,fy);
  173.  /* do first line (forward differene)*/
  174.  getdistances(fxbuf[0],fybuf[0]);
  175.  doline(fxbuf[0],fxbuf[0],fxbuf[1],fybuf[0],fybuf[0],fybuf[1],1,fg,fd);
  176.  /* do middle lines (central diffrence) */
  177.  printf("Begining computation of  views\n");
  178.  for(z=0;z<(NLINES-2);z++){      /*for each slice */
  179.      getdistances(fxbuf[mid],fybuf[mid]);
  180.      doline(fxbuf[mid],fxbuf[prev(mid)],fxbuf[succ(mid)],
  181.             fybuf[mid],fybuf[prev(mid)],fybuf[succ(mid)],2,fg,fd);
  182.      fread(fxbuf[prev(mid)],1,FLOAT_LINE,fx);
  183.      fread(fybuf[prev(mid)],1,FLOAT_LINE,fy);
  184.      mid=succ(mid);
  185.      printf(" did %d \n",z);
  186.  }
  187.  /* do last line (backward difference)*/
  188.  getdistances(fxbuf[mid],fybuf[mid]);
  189.  doline(fxbuf[mid],fxbuf[prev(mid)],fxbuf[mid],
  190.             fybuf[mid],fybuf[prev(mid)],fybuf[mid],1,fg,fd);
  191.  fclose(fg);
  192.  fclose(fd);
  193.  fclose(fx);
  194.  fclose(fy);
  195. }
  196. /**********************************************************/
  197. /**** MAIN ***** MAIN ***** MAIN ***** MAIN ***** MAIN ****/
  198. /**********************************************************/
  199. main()
  200. {
  201.  /* first get some parameters from user */
  202.  printf("Enter angle: ");
  203.  scanf("%f",&THETA);
  204.  IXmax=255*(1-THETA/90);
  205.  IYmax=255*(THETA/90);
  206.  THETA*=PI/180;
  207.  sinTheta=sin(THETA);
  208.  cosTheta=cos(THETA);
  209.  tgnTheta=sinTheta/cosTheta;
  210.  printf("Enter number of lines: ");
  211.  scanf("%d",&NLINES);
  212.  doviews();
  213. }
  214.